package single;

//懒汉式

public class Lazy {

    private Lazy(){

    }

    private volatile static Lazy lazy;
    //多线程不安全
//    public Lazy getInstance(){
//        if(lazy == null){
//            lazy = new Lazy();
//        }
//        return lazy;
//    }
    public static Lazy getInstance(){
        if(lazy == null){
            //类锁：对该类所有对象都生效
            synchronized (Lazy.class){
                if(lazy == null){
                    lazy = new Lazy();//不是原子性操作
                    /**
                     * new一个对象的步骤
                     * 1、分配内存空间
                     * 2、执行构造方法，初始化对象
                     * 3、引用指向该对象
                     *
                     * cpu有可能对上述三步指令进行重排，假如A线程对执行上述步骤顺序为132，那么，当它执行到3时，
                     * 线程B抢占进来后，误以为这个引用已经指向好了一个对象（但其实没有，因为第二步还没做），于是线程3就return了这个引用，
                     * 将会导致空指针异常，所以此时应该用volatile修饰lazy，保证lazy的及时可见性
                     */
                }
            }
        }
        return lazy;
    }

    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {

                    System.out.println(Lazy.getInstance());
                }
            }).start();
        }
    }
}
